package api

import (
	"context"
	"fmt"
	"github.com/dgrijalva/jwt-go"
	"github.com/gin-gonic/gin"
	"github.com/redis/go-redis/v9"
	"go.uber.org/zap"
	"net/http"
	"strconv"
	"time"
	"web_end/forms"
	"web_end/global"
	"web_end/global/response"
	"web_end/middleware"
	"web_end/model"
	"web_end/proto"
	"web_end/utils"
)

func HandleUserResponse(raw *proto.UserInfoResponse) *response.UserResponse {
	return &response.UserResponse{
		Id:       raw.UserId,
		Nickname: raw.Nickname,
		Mobile:   raw.Mobile,
		Birthday: raw.Birthday,
		Gender:   raw.Gender,
	}
}

// GetUserList /* 获取用户列表
func GetUserList(ctx *gin.Context) {
	userServerClient := *utils.CreateUserServerGrpc("GetUserList", "获取用户列表")

	userId, _ := ctx.Get("userId")
	zap.S().Infof("访问用户: %v", userId)

	// 获取请求参数
	pageNumberStr := ctx.DefaultQuery("pn", "0")
	pageNumberInt, _ := strconv.Atoi(pageNumberStr)
	pageSizeStr := ctx.DefaultQuery("ps", "10")
	pageSizeInt, _ := strconv.Atoi(pageSizeStr)

	rsp, err := userServerClient.GetUserList(ctx, &proto.PageInfo{
		PageNumber: int32(pageNumberInt),
		PageSize:   int32(pageSizeInt),
	})
	if err != nil {
		zap.S().Errorw("[GetUserList] 查询 [用户列表] 失败")
		utils.HandleGrpcErrorToHttp(err, ctx)
		return
	}

	result := make([]interface{}, 0)
	for _, val := range rsp.UserList {
		user := response.UserResponse{
			Id:       val.UserId,
			Nickname: val.Nickname,
			Birthday: val.Birthday,
			Mobile:   val.Mobile,
			Gender:   val.Gender,
		}

		result = append(result, user)
	}
	ctx.JSON(http.StatusOK, gin.H{
		"msg":  response.MsgSuccess,
		"code": response.CodeOk,
		"list": result,
	})
}

// PasswordLogin /* 密码登录
func PasswordLogin(ctx *gin.Context) {
	passwordLoginForm := forms.PasswordLoginForm{}
	if err := ctx.ShouldBindJSON(&passwordLoginForm); err != nil {
		ctx.JSON(http.StatusOK, gin.H{
			"msg":  response.MsgParamsError,
			"code": response.CodeBadRequest,
		})
		return
	}

	// 进行图形验证码验证
	if !store.Verify(passwordLoginForm.CaptchaId, passwordLoginForm.Captcha, true) {
		ctx.JSON(http.StatusOK, gin.H{
			"code": response.CodeBadRequest,
			"msg":  response.MsgVerifyCodeError,
		})
		return
	}

	// 生成grpc的client并调用接口
	userServerClient := *utils.CreateUserServerGrpc("PasswordLogin", "密码登录")

	// 登录逻辑
	rsp, err := userServerClient.GetUserByMobile(ctx, &proto.MobileRequest{
		Mobile: passwordLoginForm.Mobile,
	})
	if err != nil {
		zap.S().Errorw("[GetUserByMobile] 查询 [用户] 失败")
		utils.HandleGrpcErrorToHttp(err, ctx)
		return
	}

	_, err = userServerClient.CheckPassword(ctx, &proto.CheckPasswordInfo{
		RawPassword:       passwordLoginForm.Password,
		EncryptedPassword: rsp.Password,
	})
	if err != nil {
		ctx.JSON(http.StatusOK, gin.H{
			"msg":  "登录失败",
			"code": response.CodeInternalServerError,
		})
		return
	}

	j := middleware.NewJWT()
	claims := model.CustomClaims{
		ID:          rsp.UserId,
		Nickname:    rsp.Nickname,
		AuthorityId: uint(rsp.Role),
		StandardClaims: jwt.StandardClaims{
			NotBefore: time.Now().Unix(), // 签名的生效时间
			ExpiresAt: time.Now().Unix() + 60*60*24*30,
			Issuer:    "pm",
		},
	}

	token, err := j.CreateToken(claims)
	if err != nil {
		ctx.JSON(http.StatusOK, gin.H{
			"code": response.CodeInternalServerError,
			"msg":  "生成token失败",
		})
		return
	}

	user := response.UserResponse{
		Id:       rsp.UserId,
		Nickname: rsp.Nickname,
		Birthday: rsp.Birthday,
		Mobile:   rsp.Mobile,
		Gender:   rsp.Gender,
	}

	data := map[string]interface{}{
		"user":       user,
		"token":      token,
		"expired_at": (time.Now().Unix() + 60*60*24*30) * 1000, // 毫秒级别
	}

	ctx.JSON(http.StatusOK, gin.H{
		"msg":  response.MsgSuccess,
		"code": response.CodeOk,
		"data": data,
	})
}

// Register /* 用户注册
func Register(ctx *gin.Context) {
	registerForm := forms.RegisterForm{}
	if err := ctx.ShouldBindJSON(&registerForm); err != nil {
		ctx.JSON(http.StatusOK, gin.H{
			"msg":  response.MsgParamsError,
			"code": response.CodeBadRequest,
		})
		return
	}

	// 校验验证码
	smsPhone := fmt.Sprintf("sms:phone:%s", registerForm.Mobile)
	code, err := global.Rd.Get(context.Background(), smsPhone).Result()
	if err == redis.Nil || code != registerForm.Code {
		ctx.JSON(http.StatusOK, gin.H{
			"code": response.CodeBadRequest,
			"msg":  response.MsgVerifyCodeError,
		})
		return
	}

	// 生成grpc的client并调用接口
	userServerClient := *utils.CreateUserServerGrpc("Register", "用户注册")
	_, err = userServerClient.CreateUser(context.Background(), &proto.CreateUserInfo{
		Mobile:   registerForm.Mobile,
		Password: registerForm.Password,
		Nickname: registerForm.Mobile,
	})
	if err != nil {
		zap.S().Errorw("[Register] 注册 [用户] 失败")
		utils.HandleGrpcErrorToHttp(err, ctx)
		return
	}

	ctx.JSON(http.StatusOK, gin.H{
		"code": response.CodeOk,
		"msg":  response.MsgSuccess,
	})
}
